package db

import (
	"context"
	"ginfwk/infrastructure/component/config"
	"ginfwk/infrastructure/component/logger"
	"go.uber.org/zap"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"log"
)

var globalDB *gorm.DB
var globalDBConfigurator *DBConfigurator

// 1. 使用全局变量,包内完成全局配置初始化
// 2. 新增CtxXx(*context)方法,手动新建一个有上下文的对象

type DBConfigurator struct {
	dialector gorm.Dialector // 链接配置
	options   []gorm.Option  // 链接选项
}

func CtxDB(ctx context.Context, ctxLogger *zap.SugaredLogger) *gorm.DB {
	return getGlobalDB().Session(&gorm.Session{
		// NewDB: true,
		Logger: logger.NewGormLogger(ctxLogger),
		// SkipDefaultTransaction: true,
		Context: ctx,
	})
}

func getGlobalDB() *gorm.DB {
	// 建立链接(延迟初始化)
	if globalDB == nil {
		db, err := gorm.Open(globalDBConfigurator.dialector, globalDBConfigurator.options...)
		if err != nil {
			log.Printf("[ERROR] open db connection failed: %s \n", err)
		}
		globalDB = db
	}
	return globalDB
}

// Init 建立新连接
func Init(database *config.Database) error {
	var dialector gorm.Dialector // 链接配置
	var options []gorm.Option    // 链接选项

	switch database.DbType {
	case "mysql":
		dialector = NewMySQLConfig(database.MySQL)

		// 全局禁用事务 (需要时手动开启)
		options = append(options, &gorm.Config{
			SkipDefaultTransaction: true,
		})
	default:
		log.Fatalf("can`t open db connection, unknown db_type: %s", database.DbType)
	}

	// 补充通用配置
	// options = append(options, getOptions()...)

	globalDBConfigurator = &DBConfigurator{
		dialector: dialector,
		options:   options,
	}
	return nil
}

func NewMySQLConfig(cfg *config.MySQL) gorm.Dialector {
	return mysql.New(mysql.Config{
		DriverName:                    cfg.DriverName,
		ServerVersion:                 cfg.ServerVersion,
		DSN:                           cfg.DSN,
		SkipInitializeWithVersion:     cfg.SkipInitializeWithVersion,
		DefaultStringSize:             cfg.DefaultStringSize,
		DisableWithReturning:          cfg.DisableWithReturning,
		DisableDatetimePrecision:      cfg.DisableDatetimePrecision,
		DontSupportRenameIndex:        cfg.DontSupportRenameIndex,
		DontSupportRenameColumn:       cfg.DontSupportRenameColumn,
		DontSupportForShareClause:     cfg.DontSupportForShareClause,
		DontSupportNullAsDefaultValue: cfg.DontSupportNullAsDefaultValue,
		DontSupportRenameColumnUnique: cfg.DontSupportRenameColumnUnique,
	})
}
